#include "behavior_tree/behavior_tree.h"

#include <behaviortree_cpp/loggers/bt_cout_logger.h>
#include <gtest/gtest.h>

#include <sstream>

class BehaviorTreeTest : public ::testing::Test
{
  protected:
    void SetUp() override
    {
        factory_.registerNodeType<IsRaining>("IsRaining");
        factory_.registerNodeType<StayHome>("StayHome");
        factory_.registerNodeType<GoOut>("GoOut");

        // 重定向cout
        original_cout = std::cout.rdbuf();
        std::cout.rdbuf(buffer.rdbuf());

        blackboard_ = BT::Blackboard::create();
        tree_ = factory_.createTreeFromFile("../share/tree.xml", blackboard_);
        // BT::StdCoutLogger logger_cout(tree_);
    }

    void TearDown() override { std::cout.rdbuf(original_cout); }

    bool outputContains(const std::string& substr)
    {
        std::string output = buffer.str();
        return output.find(substr) != std::string::npos;
    }

    void clearOutputBuffer() { buffer.str(""); }

    BT::BehaviorTreeFactory factory_;
    BT::Tree tree_;
    BT::Blackboard::Ptr blackboard_;
    std::streambuf* original_cout;
    std::stringstream buffer;
};

TEST_F(BehaviorTreeTest, RainyDayScenario)
{
    blackboard_->set<bool>("is_raining", true);
    clearOutputBuffer();

    auto status = tree_.tickWhileRunning();
    EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
    EXPECT_TRUE(outputContains("天气状态: 下雨"));
    EXPECT_TRUE(outputContains("躺平追剧"));
    EXPECT_FALSE(outputContains("出门散步"));
}

TEST_F(BehaviorTreeTest, SunnyDayScenario)
{
    blackboard_->set<bool>("is_raining", false);
    clearOutputBuffer();

    auto status = tree_.tickWhileRunning();
    EXPECT_EQ(status, BT::NodeStatus::SUCCESS);
    EXPECT_TRUE(outputContains("天气状态: 晴天"));
    EXPECT_TRUE(outputContains("出门散步"));
    EXPECT_FALSE(outputContains("躺平追剧"));
}